/*
 * AbstractFont.java
 *
 * Created on 2008/08/25 +0900
 *
 * $Revision: 38 $
 * $Date: 2008-10-11 08:48:45 +0000 (Sat, 11 Oct 2008) $
 */

package org.gikolet.framework.ui;

import org.gikolet.framework.util.Assert;

/**
 * @author tetsutaro (latest modification by $Author: tetsutaro.ss $)
 * @version $Revision: 38 $ $Date: 2008-10-11 08:48:45 +0000 (Sat, 11 Oct 2008) $
 */
public abstract class AbstractFont implements Font {
    private FontProvider fontProvider;

    // このフォントのフェイス
    private int face;

    // このフォントのスタイル
    private int style;

    // このフォントのサイズ
    private int size;

    protected AbstractFont(FontProvider fontProvider, int face, int style, int size) {
	Assert.isNotNull(fontProvider);

	this.fontProvider = fontProvider;

	checkFace(face);
	this.face = face;

	checkStyle(style);
	this.style = style;

	checkSize(this.fontProvider, size);
	this.size = size;
    }

    protected static void checkFace(int face) {
	// フェイスのチェック
	switch (face) {
	    case FACE_MONOSPACE:
	    case FACE_PROPORTIONAL:
	    case FACE_SYSTEM:
		break;
	    default:
		throw new IllegalArgumentException("Invalid face is " + face);
	}
    }

    protected static void checkStyle(int style) {
	/*
	 * スタイルのチェック ssは最後で余計なものが指定されていないかをチェックするためにある。
	 * つまり、styleに指定されているスタイルの値を引いていくと0になるので、 チェックできる。
	 */
	int ss = style;
	if ((style & Font.STYLE_PLAIN) != 0) {
	    if ((style & Font.STYLE_BOLD) != 0 || (style & Font.STYLE_ITALIC) != 0) {
		// スタイルにボールドかイタリックが指定してあったら例外をスローする。
		throw new IllegalArgumentException("Invalid style is " + style);
	    }
	    ss -= Font.STYLE_PLAIN;
	} else {
	    if ((style & Font.STYLE_BOLD) != 0) {
		ss -= Font.STYLE_BOLD;
	    }
	    if ((style & Font.STYLE_ITALIC) != 0) {
		ss -= Font.STYLE_ITALIC;
	    }
	}

	if ((style & Font.STYLE_UNDERLINED) != 0) {
	    ss -= Font.STYLE_UNDERLINED;
	}
	if (ss != 0) {
	    // すべての引き数のstyleからすべてのスタイルを引いた結果0でなかったので例外をスローする。
	    throw new IllegalArgumentException("Invalid style is " + style);
	}
    }

    protected static void checkSize(FontProvider fontProvider, int size) {
	/*
	 * サイズのチェック サイズには論理的、物理的なフォントサイズを指定できるので、それぞれチェック。
	 */
	switch (size) {
	    case SIZE_LARGE:
	    case SIZE_MEDIUM:
	    case SIZE_SMALL:
	    case SIZE_TINY:
		break;
	    default:
		if (size <= 0) {
		    // 物理的なフォントサイズでは0以下は不正なので、例外をスローする。
		    throw new IllegalArgumentException("Invalid size is " + size);
		} else {
		    if (fontProvider.isSupportedFontSize(size)) {
			throw new IllegalArgumentException("Invalid size is " + size);
		    }
		}
	}
    }

    public FontProvider getFontProvider() {
	return this.fontProvider;
    }

    /*
     * このフォントのフェイスを返す。
     */
    public int getFace() {
	return this.face;
    }

    /*
     * このフォントのスタイルを組み合わせた値で返す。
     */
    public int getStyle() {
	return this.style;
    }

    /*
     * このフォントがプレーンスタイルかを返す。
     */
    public boolean isPlain() {
	return (this.style & STYLE_PLAIN) != 0;
    }

    /*
     * このフォントがボールドスタイルかを返す。
     */
    public boolean isBold() {
	return (this.style & STYLE_BOLD) != 0;
    }

    /*
     * このフォントがイタリックスタイルかを返す。
     */
    public boolean isItalic() {
	return (this.style & STYLE_ITALIC) != 0;
    }

    /*
     * このフォントがアンダーラインスタイルかを返す。
     */
    public boolean isUnderlined() {
	return (this.style & STYLE_UNDERLINED) != 0;
    }

    /*
     * このフォントのサイズを返す。
     */
    public int getSize() {
	return this.size;
    }
}
